
from comlibpy.func import vparam, vparam1
from typing import Any,Union

import operator
import math, cmath

def powerOne(base:Union[complex, float],
          exp:Union[complex,float],
          kscope:list[int] = [0]
          ) -> list[complex]:
    
    if isinstance(base, float):
        base = complex(base, 0)

    if isinstance(exp, float):
        exp = complex(exp, 0)

    r = abs(base)
    theta = cmath.phase(base)

    size_a = math.pow(r, exp.real)
    phase_a = exp.imag * math.log(r)

    def one(x:float, y:float, t:float) -> complex:
        size_b = math.exp(-1 * y * t)
        phase_b = x * t
        size = size_a * size_b
        phase = phase_a + phase_b

        return complex( size * math.cos(phase), size * math.sin(phase) )

    return [one(exp.real, exp.imag, theta + 2 * k * math.pi
                for k in kscope]

def power(base:Union[list, complex, float],
          exp:Union[list, complex, float],
          kscope:list[int] = [0]
          ) -> list[list[complex]]:
    
    if not isinstance(base, list):
        base = [base]

    if not isinstance(exp, list):
        exp = [exp]

    if len(base) == 1:
        base = base * len(exp)
    elif len(exp) == 1:
        exp = exp * len(base)
    else:
        assert len(base) == len(exp), f"Must be same dimsion size"
        

    return [powerOne(b, e, kscope) for (b, e) in zip(base, exp)]



xand = vparam( operator.and_ )
xor = vparam( operator.xor )
xxor = vparam( operator.xor )

xadd = vparam( operator.add )
xsub = vparam( operator.sub )
xmul = vparam( operator.mul )
xdiv = vparam( operator.truediv )
xfloor = vparam( operator.floordiv )
xmod = vparam( operator.mod )
xpow = vparam( operator.pow )


xmin = vparam( min )
xmax = vparam( max )

def ceil(a, b=1):
    if a % b == 0: return a
    return int( math.ceil( a / b ) * b )


def gcd(a,b):
    if a < b:
        a,b = b,a
    remainder = a % b
    if remainder == 0:
        return b
    else:
        return gcd(remainder,b)

def sumwgt(wgt,rate):
    rates = sum(map(lambda x,y: x*y, wgt, rate))
    wgts = sum(iter(wgt))
    return rates / wgts


xceil = vparam1( ceil )
xgcd = vparam( gcd )
xsumwgt = vparam( sumwgt )
